import {
  useDebounceFn,
  useMount,
  usePagination,
  useResetState,
  useUpdateEffect,
} from "ahooks";
import { Row, Select, SelectProps, Spin } from "antd";
import type { DefaultOptionType } from "antd/es/select";
import React from "react";

type TParams = {
  page: number;
  size: number;
  [prop: string]: string | number;
};

type TData = {
  total: number;
  records: DefaultOptionType[];
};

export interface ScrollLoadSelectProps extends SelectProps {
  /** debounce 时间 单位ms */
  wait?: number;
  defaultSearch?: string;
  params?: Record<string, any>;
  disabledValues?: (string | number)[];
  /**
   * 搜索字段名称
   * @default keyword
   */
  searchName?: string;
  /**
   * 每页条数
   * @default 10
   */
  pageSize?: number;
  /**
   * 是否自动发起请求
   * @default false
   */
  autoSearch?: boolean;
  /** 远程搜索方法 */
  request: (params: TParams) => Promise<TData>;
}

/**
 * 滚动加载下拉框
 * @param wait
 * @param pageSize
 * @param defaultSearch
 * @param params
 * @param searchName
 * @param autoSearch
 * @param disabledValues
 * @param request
 * @param props
 * @returns
 */
export default function ScrollLoadSelect({
  wait = 600,
  pageSize = 10,
  defaultSearch,
  params,
  searchName = "keyword",
  autoSearch = true,
  disabledValues,
  request,
  ...props
}: ScrollLoadSelectProps) {
  const [optionData, setOptionData, reset] = useResetState({
    total: 0,
    list: [] as DefaultOptionType[],
  });
  const {
    data,
    run: getList,
    loading,
    pagination,
  } = usePagination(
    async ({ current, pageSize, keyword }) => {
      console.log(111);
      const res = await request({
        page: current,
        size: pageSize,
        ...params,
        [searchName]: keyword,
      });
      return {
        total: res.total,
        list: res.records,
      };
    },
    {
      manual: true,
    }
  );

  const { run } = useDebounceFn(
    (keyword?: string) => {
      getList({
        current: 1,
        pageSize,
        keyword,
      });
      reset();
    },
    { wait }
  );

  useMount(() => {
    if (autoSearch) {
      run(defaultSearch);
    }
  });

  useUpdateEffect(() => {
    run();
  }, [params]);

  React.useLayoutEffect(() => {
    setOptionData((pre) => {
      if (data?.list?.length) {
        return {
          total: data.total,
          list: [...pre.list, ...data.list],
        };
      }
      return pre;
    });
  }, [data]);

  const options = optionData.list;

  if (disabledValues?.length) {
    const valueName = props.fieldNames?.value ?? "value";
    options.forEach((option) => {
      option.disabled = disabledValues.includes(option[valueName]);
    });
  }

  return (
    <Select
      {...props}
      showSearch
      filterOption={false}
      onSearch={run}
      options={optionData.list}
      notFoundContent={
        loading ? (
          <Row justify="center">
            <Spin size="small" />
          </Row>
        ) : (
          void 0
        )
      }
      onPopupScroll={(e) => {
        e.stopPropagation();
        if (pagination.current < pagination.totalPage) {
          const { target } = e as unknown as { target: HTMLElement };
          const { scrollTop, offsetHeight, scrollHeight } = target;
          if (scrollTop + offsetHeight >= scrollHeight) {
            pagination.onChange(pagination.current + 1, pageSize);
          }
        }
      }}
      dropdownRender={(menu) => (
        <>
          {menu}
          {loading && pagination.current > 1 && (
            <Row justify="center">
              <Spin size="small" />
            </Row>
          )}
        </>
      )}
    />
  );
}
